package deviceScript

import (
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Json"
	"github.com/dop251/goja"
	"go-fox-edge-device/deviceLogger"
	"strings"
)

type ScriptEngineOperator struct {
}

func (e *ScriptEngineOperator) setSendEnvValue(engine *goja.Runtime, params map[string]interface{}) error {
	return engine.Set("fox_edge_param", Json.BuildJson(params))
}

func (e *ScriptEngineOperator) setRecvEnvValue(engine *goja.Runtime, recv interface{}, params map[string]interface{}) error {
	err := engine.Set("fox_edge_param", Json.BuildJson(params))
	if err != nil {
		return err
	}

	switch recv.(type) {
	case map[string]interface{}:
		return engine.Set("fox_edge_data", Json.BuildJson(recv))
	case []interface{}:
		return engine.Set("fox_edge_data", Json.BuildJson(recv))
	case string:
		return engine.Set("fox_edge_data", recv)
	default:
		return engine.Set("fox_edge_data", "")
	}

	deviceLogger.PrintLogger("对通道返回的数据，只支持String、Map、List三种数据结构！")
	return nil
}

func (e *ScriptEngineOperator) decodeRecord(engine *goja.Runtime, operateName string, decodeMain string, decodeScript string) (rtn map[string]interface{}, err error) {
	// 定义一个最终的异常拦截，用来防止可能的代码BUG
	defer func() {
		if r := recover(); r != nil {
			message := fmt.Sprintf("deviceScript.runScript() 捕获到异常:%v", r)
			err = errors.New(message)
			deviceLogger.PrintLogger(message)
		}
	}()

	// 重新装载待待执行的脚本
	_, err = engine.RunString(decodeScript)
	if err != nil {
		return nil, err
	}

	// 执行JSP脚本中的函数
	decode, ok := goja.AssertFunction(engine.Get(decodeMain))
	if !ok {
		return nil, errors.New("未定义函数：" + decodeMain)
	}

	// 执行函数
	res, err := decode(goja.Undefined())
	if err != nil {
		deviceLogger.PrintLogger("执行解码函数出错：" + err.Error())
		return nil, err
	}
	jsn := res.String()

	//再将JSON格式的字符串，转换回List<Map>
	var values []map[string]interface{}
	err = json.Unmarshal([]byte(jsn), &values)
	if err != nil {
		return nil, err
	}

	recordValue := make(map[string]interface{})
	recordValue[EnumRecord] = values

	result := make(map[string]interface{})
	result[enumOperateName] = operateName
	result[enumData] = recordValue

	return result, nil
}

func (e *ScriptEngineOperator) decodeStatus(engine *goja.Runtime, operateName string, decodeMain string, decodeScript string) (rtn map[string]interface{}, err error) {
	// 定义一个最终的异常拦截，用来防止可能的代码BUG
	defer func() {
		if r := recover(); r != nil {
			message := fmt.Sprintf("deviceScript.runScript() 捕获到异常:%v", r)
			err = errors.New(message)
			deviceLogger.PrintLogger(message)
		}
	}()

	// 重新装载待待执行的脚本
	_, err = engine.RunString(decodeScript)
	if err != nil {
		return nil, err
	}

	// 执行JSP脚本中的函数
	decode, ok := goja.AssertFunction(engine.Get(decodeMain))
	if !ok {
		return nil, errors.New("未定义函数：" + decodeMain)
	}

	// 执行函数
	res, err := decode(goja.Undefined())
	if err != nil {
		deviceLogger.PrintLogger("执行解码函数出错：" + err.Error())
		return nil, err
	}
	jsn := res.String()

	//再将JSON格式的字符串，转换回Map
	var values map[string]interface{}
	err = json.Unmarshal([]byte(jsn), &values)
	if err != nil {
		return nil, err
	}

	result := make(map[string]interface{})
	result[EnumStatus] = values

	return result, nil
}

func (e *ScriptEngineOperator) decodeResult(engine *goja.Runtime, operateName string, decodeMain string, decodeScript string) (rtn map[string]interface{}, err error) {
	// 定义一个最终的异常拦截，用来防止可能的代码BUG
	defer func() {
		if r := recover(); r != nil {
			message := fmt.Sprintf("deviceScript.runScript() 捕获到异常:%v", r)
			err = errors.New(message)
			deviceLogger.PrintLogger(message)
		}
	}()

	// 重新装载待待执行的脚本
	_, err = engine.RunString(decodeScript)
	if err != nil {
		return nil, err
	}

	// 执行JSP脚本中的函数
	decode, ok := goja.AssertFunction(engine.Get(decodeMain))
	if !ok {
		return nil, errors.New("未定义函数：" + decodeMain)
	}

	// 执行函数
	res, err := decode(goja.Undefined())
	if err != nil {
		deviceLogger.PrintLogger("执行javascript函数出错：" + err.Error())
		return nil, err
	}
	jsn := res.String()

	//再将JSON格式的字符串，转换回Map
	var values map[string]interface{}
	err = json.Unmarshal([]byte(jsn), &values)
	if err != nil {
		return nil, err
	}

	recordValue := make(map[string]interface{})
	recordValue[EnumRecord] = values

	result := make(map[string]interface{})
	result[enumOperateName] = operateName
	result[EnumResult] = recordValue

	return result, nil
}

func (e *ScriptEngineOperator) encode(engine *goja.Runtime, encodeMain string, decodeScript string) (rtn interface{}, err error) {
	// 定义一个最终的异常拦截，用来防止可能的代码BUG
	defer func() {
		if r := recover(); r != nil {
			message := fmt.Sprintf("deviceScript.runScript() 捕获到异常:%v", r)
			err = errors.New(message)
			deviceLogger.PrintLogger(message)
		}
	}()

	// 重新装载待待执行的脚本
	_, err = engine.RunString(decodeScript)
	if err != nil {
		return nil, err
	}

	// 执行JSP脚本中的函数
	encode, ok := goja.AssertFunction(engine.Get(encodeMain))
	if !ok {
		return nil, errors.New("未定义函数：" + encodeMain)
	}

	// 执行函数
	res, err := encode(goja.Undefined())
	if err != nil {
		deviceLogger.PrintLogger("执行编码函数出错：" + err.Error())
		return nil, err
	}
	out := res.String()

	// 根据文本格式，转为Map/List，或者是原始的字符串
	if strings.HasPrefix(out, "{") && strings.HasSuffix(out, "}") {
		var value map[string]interface{}
		err = json.Unmarshal([]byte(out), &value)
		if err != nil {
			return nil, err
		}

		return value, nil
	} else if strings.HasPrefix(out, "[") && strings.HasSuffix(out, "]") {
		var value []map[string]interface{}
		err = json.Unmarshal([]byte(out), &value)
		if err != nil {
			return nil, err
		}

		return value, nil
	} else {
		return out, nil
	}
}
